#include "Parser.h"


Parser::Parser(void)
{
	n_textures = 0;
	current_view = -1;
}

Parser::~Parser(void)
{
}

void Parser::loadIllumination(TiXmlElement* illuminationElem){
	if(illuminationElem == NULL){
		printf("illumination block does not exist\n");
		getchar();
		exit(1);
	}

	int boolean;
	if(illuminationElem->QueryIntAttribute("doublesided",&boolean) != TIXML_SUCCESS
		|| (boolean != 0 && boolean != 1))
	{
		printf("error reading doublesided attribute of element illumination");
		getchar();
		exit(1);
	}
	illumination.doublesided = boolean;

	if(illuminationElem->QueryIntAttribute("local",&boolean) != TIXML_SUCCESS ||
		(boolean != 0 && boolean != 1))
	{
		printf("error reading local attribute of element illumination");
		getchar();
		exit(1);
	}
	illumination.local = boolean;

	TiXmlElement* illuminationChild = illuminationElem->FirstChildElement("ambient");
	if(illuminationChild == NULL){
		printf("illumination block does not have ambient element\n");
		getchar();
		exit(1);
	}
	if (illuminationChild->QueryFloatAttribute("r",&illumination.ambient[0])!=TIXML_SUCCESS || 
		illuminationChild->QueryFloatAttribute("g",&illumination.ambient[1])!=TIXML_SUCCESS ||
		illuminationChild->QueryFloatAttribute("b",&illumination.ambient[2])!=TIXML_SUCCESS ||
		illuminationChild->QueryFloatAttribute("a",&illumination.ambient[3])!=TIXML_SUCCESS)
	{
		printf("error loading ambient attributes of illumination");
		getchar();
		exit(1);
	}

	illuminationChild = illuminationElem->FirstChildElement("background");
	if(illuminationChild == NULL){
		printf("illumination block does not have ambient element\n");
		getchar();
		exit(1);
	}
	if (illuminationChild->QueryFloatAttribute("r",&illumination.background[0])!=TIXML_SUCCESS || 
		illuminationChild->QueryFloatAttribute("g",&illumination.background[1])!=TIXML_SUCCESS ||
		illuminationChild->QueryFloatAttribute("b",&illumination.background[2])!=TIXML_SUCCESS ||
		illuminationChild->QueryFloatAttribute("a",&illumination.background[3])!=TIXML_SUCCESS)
	{
		printf("error loading background attributes of illumination");
		getchar();
		exit(1);
	}
}

void Parser::loadViews(TiXmlElement* viewsElem){
	if(viewsElem == NULL){
		printf("views block does not exist");
		getchar();
		exit(1);
	}

	if(viewsElem->Attribute("default") == NULL){
		printf("views block does not have default attribute");
		getchar();
		exit(1);
	}
	string default_view = viewsElem->Attribute("default");

	TiXmlElement* viewElem = viewsElem->FirstChildElement();
	if(viewElem ==NULL){
		printf("views block does not have children");
		getchar();
		exit(1);
	}
	
	string id, type;
	float near, far, angle;
	float from_x, from_y, from_z;
	float to_x, to_y, to_z;
	float top, bottom, left, right;
	TiXmlElement* perspectiveChildren;

	do{
		type = viewElem->Value();

		if(viewElem->Attribute("id") == NULL){
			printf("view does not have id");
			getchar();
			exit(1);
		}
		id = viewElem->Attribute("id");

		if(type == "perspective"){
			if(	viewElem->QueryFloatAttribute("near",&near) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("far",&far) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("angle",&angle) != TIXML_SUCCESS)
			{
				printf("error reading attributes of perspective id = %s",id.c_str());
				getchar();
				exit(1);
			}

			perspectiveChildren = viewElem->FirstChildElement("from");
			if(perspectiveChildren == NULL){
				printf("perspective id = %s does not have from element",id.c_str());
				getchar();
				exit(1);
			}
			if(	perspectiveChildren->QueryFloatAttribute("x",&from_x) != TIXML_SUCCESS ||
				perspectiveChildren->QueryFloatAttribute("y",&from_y) != TIXML_SUCCESS ||
				perspectiveChildren->QueryFloatAttribute("z",&from_z) != TIXML_SUCCESS)
			{
				printf("error reading attributes of from element of perspective id = %s",id.c_str());
				getchar();
				exit(1);
			}

			perspectiveChildren = viewElem->FirstChildElement("to");
			if(perspectiveChildren == NULL){
				printf("perspective id = %s does not have to element",id.c_str());
				getchar();
				exit(1);
			}
			if(	perspectiveChildren->QueryFloatAttribute("x",&to_x) != TIXML_SUCCESS ||
				perspectiveChildren->QueryFloatAttribute("y",&to_y) != TIXML_SUCCESS ||
				perspectiveChildren->QueryFloatAttribute("z",&to_z) != TIXML_SUCCESS)
			{
				printf("error reading attributes of to element of perspective id = %s",id.c_str());
				getchar();
				exit(1);
			}

			views.push_back( new PerspectiveParser(id,near,far,angle,from_x,from_y,from_z,to_x,to_y,to_z));

		}
		else if(type == "ortho"){
			if(	viewElem->QueryFloatAttribute("near",&near) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("far",&far) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("left",&left) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("right",&right) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("top",&top) != TIXML_SUCCESS ||
				viewElem->QueryFloatAttribute("bottom",&bottom) != TIXML_SUCCESS)
			{
				printf("error reading attributes of ortho id = %s",id.c_str());
				getchar();
				exit(1);
			}
			views.push_back(new OrthoParser(id,near,far,left,right,top,bottom));
		}
		else{
			printf("invalid view type %s", type.c_str());
			getchar();
			exit(1);
		}
		if(id == default_view)
			current_view = views.size() - 1;
	}while((viewElem = viewElem->NextSiblingElement()) != NULL);

	//current_view = views.find(default_view);
	if(current_view == -1/*current_view == views.end()*/){
		printf("default view %s does not exist",default_view.c_str());
		getchar();
		exit(1);
	}
}

void Parser::loadLights(TiXmlElement* lightsElem){
	if(lightsElem == NULL){
		printf("lights block does not exist");
		getchar();
		exit(1);
	}

	TiXmlElement* lightElem = lightsElem->FirstChildElement();
	string id, type;
	float enabled, angle, exponent;

	do{
		type = lightElem->Value();

		if(lightElem->Attribute("id") == NULL){
			printf("Error reading light id");
			getchar();
			exit(1);
		}
		id = lightElem->Attribute("id");

		if(lightElem->QueryFloatAttribute("enabled",&enabled) != TIXML_SUCCESS ||
			(enabled != 0 && enabled !=1))
		{
			printf("Error reading light id = %s enabled attribute",id.c_str());
			getchar();
			exit(1);
		}

		LightParser* light;
		TiXmlElement* lightComponents = lightElem->FirstChildElement("location");
		if(lightComponents == NULL){
			printf("light id=%s does not have location",id.c_str());
			getchar();
			exit(1);
		}

		if(type == "omni"){
			light = new OmniLightParser(id, lights.size(), enabled);

			if(lightComponents->QueryFloatAttribute("x",&light->location[0]) ||
				lightComponents->QueryFloatAttribute("y",&light->location[1]) ||
				lightComponents->QueryFloatAttribute("z",&light->location[2]) ||
				lightComponents->QueryFloatAttribute("w",&light->location[3]))
			{
				printf("error reading omni id=%s location attributes",id.c_str());
				getchar();
				exit(1);
			}
		}
		else if(type == "spot"){
			if(	lightElem->QueryFloatAttribute("angle",&angle) != TIXML_SUCCESS ||
				lightElem->QueryFloatAttribute("exponent",&exponent) != TIXML_SUCCESS)
			{
				printf("error reading spotlight id= &s attributes",id.c_str());
				getchar();
				exit(1);
			}
			light = new SpotLightParser(id,lights.size(),enabled,angle,exponent);

			if(lightComponents->QueryFloatAttribute("x",&light->location[0]) ||
				lightComponents->QueryFloatAttribute("y",&light->location[1]) ||
				lightComponents->QueryFloatAttribute("z",&light->location[2]))
			{
				printf("error reading spot id=%s location attributes",id.c_str());
				getchar();
				exit(1);
			}
			light->location[3]=1;

			lightComponents = lightElem->FirstChildElement("target");
			if(lightComponents == NULL){
				printf("spot id=%s does not have target",id.c_str());
				getchar();
				exit(1);
			}
			if(	lightComponents->QueryFloatAttribute("x",&((SpotLightParser*) light)->target[0]) ||
				lightComponents->QueryFloatAttribute("y",&((SpotLightParser*) light)->target[1]) ||
				lightComponents->QueryFloatAttribute("z",&((SpotLightParser*) light)->target[2]))
			{
				printf("error reading spot id=%s target attributes",id.c_str());
				getchar();
				exit(1);
			}
		}
		else
		{
			printf("%s invalid light type",type.c_str());
			getchar();
			exit(1);
		}

		lightComponents = lightElem->FirstChildElement("ambient");
		if(lightComponents == NULL){
			printf("light id=%s does not have ambient",id.c_str());
			getchar();
			exit(1);
		}
		if(	lightComponents->QueryFloatAttribute("r",&light->ambient[0]) ||
			lightComponents->QueryFloatAttribute("g",&light->ambient[1]) ||
			lightComponents->QueryFloatAttribute("b",&light->ambient[2]) ||
			lightComponents->QueryFloatAttribute("a",&light->ambient[3]))
		{
			printf("error reading light id=%s ambient attributes",id.c_str());
			getchar();
			exit(1);
		}

		lightComponents = lightElem->FirstChildElement("diffuse");
		if(lightComponents == NULL){
			printf("light id=%s does not have diffuse",id.c_str());
			getchar();
			exit(1);
		}
		if(	lightComponents->QueryFloatAttribute("r",&light->diffuse[0]) ||
			lightComponents->QueryFloatAttribute("g",&light->diffuse[1]) ||
			lightComponents->QueryFloatAttribute("b",&light->diffuse[2]) ||
			lightComponents->QueryFloatAttribute("a",&light->diffuse[3]))
		{
			printf("error reading light id=%s diffuse attributes",id.c_str());
			getchar();
			exit(1);
		}

		lightComponents = lightElem->FirstChildElement("specular");
		if(lightComponents == NULL){
			printf("light id=%s does not have specular",id.c_str());
			getchar();
			exit(1);
		}
		if(	lightComponents->QueryFloatAttribute("r",&light->specular[0]) ||
			lightComponents->QueryFloatAttribute("g",&light->specular[1]) ||
			lightComponents->QueryFloatAttribute("b",&light->specular[2]) ||
			lightComponents->QueryFloatAttribute("a",&light->specular[3]))
		{
			printf("error reading light id=%s specular attributes",id.c_str());
			getchar();
			exit(1);
		}

		lights.push_back(light);
		if(lights.size()>=8){
			printf("max number of lights reached\n");
			break;
		}
	}while((lightElem = lightElem->NextSiblingElement()) != NULL);
}

void Parser::loadTransformations(TiXmlElement* transformationsElem){
	if(transformationsElem == NULL){
		printf("tranformations block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* transformationElem = transformationsElem->FirstChildElement("transformation");
	if(transformationElem == NULL){
		printf("transformations block does not have children\n");
		getchar();
		exit(1);
	}

	string id;
	float x, y, z, angle;
	char axis;
	
	do{
		id = transformationElem->Attribute("id");
		if(id.size() == 0){
			printf("transformation does not have id");
			getchar();
			exit(1);
		}

		vector<TransformationParser> transfors;
		string type;
		TiXmlElement* transf = transformationElem->FirstChildElement();
		if(transf == NULL){
			printf("transformation block does not have children\n");
			getchar();
			exit(1);
		}
		
		do{
			type = transf->Value();
			
			if(type == "translate"){
				if (transf->QueryFloatAttribute("x",&x)==TIXML_SUCCESS && 
					transf->QueryFloatAttribute("y",&y)==TIXML_SUCCESS &&
					transf->QueryFloatAttribute("z",&z)==TIXML_SUCCESS)
					transfors.push_back( TransformationParser(TransformationParser::TRANSLATE,x,y,z));
				else
					printf("transfomation id= %s translate does not have all the correct attributes\n",id.c_str());
			
			}else if(type == "scale"){
				if (transf->QueryFloatAttribute("x",&x)==TIXML_SUCCESS && 
					transf->QueryFloatAttribute("y",&y)==TIXML_SUCCESS &&
					transf->QueryFloatAttribute("z",&z)==TIXML_SUCCESS)
					transfors.push_back( TransformationParser(TransformationParser::SCALE,x,y,z));
				else
					printf("scale does not have all the correct attributes\n");

			}else if(type == "rotate"){
				if (((axis = (transf->Attribute("axis"))[0])== 'x' || axis == 'y' || axis == 'z' ) && 
					transf->QueryFloatAttribute("angle",&angle)==TIXML_SUCCESS)
				{
					x = y = z = 0;
					switch(axis){
						case 'x':
							x = 1;
							break;
						case 'y':
							y = 1;
							break;
						case 'z':
							z = 1;
							break;
					}
					transfors.push_back( TransformationParser(TransformationParser::ROTATE,x,y,z,angle));
				}
				else
					printf("rotate does not have all the correct attributes\n");
			}else{
				printf("transformation not valid\n");
			}

		}while((transf = transf->NextSiblingElement()) != NULL);

		transformations[id] = transfors;
	}while((transformationElem = transformationElem->NextSiblingElement()) != NULL);
}

void Parser::loadTextures(TiXmlElement* texturesElem){
	if(texturesElem == NULL){
		printf("textures block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* textureElem = texturesElem->FirstChildElement("texture");
	if(textureElem == NULL){
		printf("textures block does not have children\n");
		getchar();
		exit(1);
	}

	string id;

	do{
		if(textureElem->Attribute("id")==NULL){
			printf("texture does not have id");
			getchar();
			exit(1);
		}
		id = textureElem->Attribute("id");

		TextureParser texture;

		if(textureElem->Attribute("file")==NULL){
			printf("texture id=%s does not have attribute file",id.c_str());
			getchar();
			exit(1);
		}
		texture.file = textureElem->Attribute("file");

		if(	textureElem->QueryFloatAttribute("length_s",&texture.length_s)!=TIXML_SUCCESS ||
			textureElem->QueryFloatAttribute("length_t",&texture.length_t)!=TIXML_SUCCESS)
		{
			printf("error loading attributes of texture id = %s",id.c_str());
			getchar();
			exit(1);
		}
		
		textures[id] = texture;
	}while((textureElem = textureElem->NextSiblingElement()) != NULL);
}

void Parser::loadMaterials(TiXmlElement* materialsElem){
	if(materialsElem == NULL){
		printf("materials block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* materialElem = materialsElem->FirstChildElement("material");
	if(materialElem == NULL){
		printf("materials block does not have children\n");
		getchar();
		exit(1);
	}

	string id;

	do{
		id = materialElem->Attribute("id");
		if(id.size() == 0){
			printf("material does not have id");
			getchar();
			exit(1);
		}

		MaterialParser mat;
		
		TiXmlElement* mat_components = materialElem->FirstChildElement("emission");
		if(mat_components == NULL){
			printf("material id = %s does not have emission component",id.c_str());
			getchar();
			exit(1);
		}
		if (mat_components->QueryFloatAttribute("r",&mat.emission[0])!=TIXML_SUCCESS || 
			mat_components->QueryFloatAttribute("g",&mat.emission[1])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("b",&mat.emission[2])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("a",&mat.emission[3])!=TIXML_SUCCESS)
		{
			printf("error loading emission attributes of material id = %s",id.c_str());
			getchar();
			exit(1);
		}

		mat_components = materialElem->FirstChildElement("ambient");
		if(mat_components == NULL){
			printf("material id = %s does not have ambient component",id.c_str());
			getchar();
			exit(1);
		}
		if (mat_components->QueryFloatAttribute("r",&mat.ambient[0])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("g",&mat.ambient[1])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("b",&mat.ambient[2])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("a",&mat.ambient[3])!=TIXML_SUCCESS)
		{
			printf("error loading ambient attributes of material id = %s",id.c_str());
			getchar();
			exit(1);
		}

		mat_components = materialElem->FirstChildElement("diffuse");
		if(mat_components == NULL){
			printf("material id = %s does not have diffuse component",id.c_str());
			getchar();
			exit(1);
		}
		if (mat_components->QueryFloatAttribute("r",&mat.diffuse[0])!=TIXML_SUCCESS || 
			mat_components->QueryFloatAttribute("g",&mat.diffuse[1])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("b",&mat.diffuse[2])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("a",&mat.diffuse[3])!=TIXML_SUCCESS)
		{
			printf("error loading diffuse attributes of material id = %s",id.c_str());
			getchar();
			exit(1);
		}

		mat_components = materialElem->FirstChildElement("specular");
		if(mat_components == NULL){
			printf("material id = %s does not have specular component",id.c_str());
			getchar();
			exit(1);
		}
		if (mat_components->QueryFloatAttribute("r",&mat.specular[0])!=TIXML_SUCCESS || 
			mat_components->QueryFloatAttribute("g",&mat.specular[1])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("b",&mat.specular[2])!=TIXML_SUCCESS ||
			mat_components->QueryFloatAttribute("a",&mat.specular[3])!=TIXML_SUCCESS)
		{
			printf("error loading specular attributes of material id = %s",id.c_str());
			getchar();
			exit(1);
		}

		mat_components = materialElem->FirstChildElement("shininess");
		if(mat_components == NULL){
			printf("material id = %s does not have shininess component",id.c_str());
			getchar();
			exit(1);
		}
		if (mat_components->QueryFloatAttribute("value",&mat.shininess[0])!=TIXML_SUCCESS)
		{
			printf("error loading shininess attributes of material id = %s",id.c_str());
			getchar();
			exit(1);
		}

		materials[id] = mat;
	}while((materialElem = materialElem->NextSiblingElement()) != NULL);
}

void Parser::loadPrimitives(TiXmlElement* primitivesElem){
	if(primitivesElem == NULL){
		printf("primitives block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* primitiveElem = primitivesElem->FirstChildElement("primitive");
	if(primitiveElem == NULL){
		printf("primitives block does not have children\n");
		getchar();
		exit(1);
	}

	string id;
	do{
		id = primitiveElem->Attribute("id");
		if(id.size() == 0){
			printf("primitive does not have id");
			getchar();
			exit(1);
		}
		string type;
		string material_id;
		TiXmlElement* prim = primitiveElem->FirstChildElement("material");
		if(prim == NULL){
			printf("primitive id = %s does not have material\n",id.c_str());
			getchar();
			exit(1);
		}
		material_id = prim->Attribute("id");
		if(material_id.size() == 0){
			printf("primitive id = %s material does not have id\n",id.c_str());
			getchar();
			exit(1);
		}

		prim = primitiveElem->FirstChildElement("texture");
		if(prim == NULL){
			printf("primitive id = %s does not have texture\n",id.c_str());
			getchar();
			exit(1);
		}
		if(prim->Attribute("id") == NULL){
			printf("primitive id = %s texture does not have id\n",id.c_str());
			getchar();
			exit(1);
		}
		string texture_id = prim->Attribute("id");

		prim = prim->NextSiblingElement();
		if(prim == NULL){
			printf("primitive does not have children\n");
			getchar();
			exit(1);
		}

		type = prim->Value();
		/*while(type == "material" || type == "texture"){
			prim = prim->NextSiblingElement();
			type = prim->Value();
		}*/

		if(type == "rectangle"){
			float x1,y1,x2,y2;
			if(prim->QueryFloatAttribute("x1",&x1)==TIXML_SUCCESS && 
				prim->QueryFloatAttribute("y1",&y1)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("x2",&x2)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("y2",&y2)==TIXML_SUCCESS)
				primitives[id] = new RectangleParser(x1,y1,x2,y2,texture_id,material_id);
			else{
				printf("rectangle does not have all the correct attributes\n");
				getchar();
				exit(1);
			}
		}
		else if(type == "triangle"){
			float x1,y1,z1,x2,y2,z2,x3,y3,z3;
			if(prim->QueryFloatAttribute("x1",&x1)==TIXML_SUCCESS && 
				prim->QueryFloatAttribute("y1",&y1)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("z1",&z1)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("x2",&x2)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("y2",&y2)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("z2",&z2)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("x3",&x3)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("y3",&y3)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("z3",&z3)==TIXML_SUCCESS)
				primitives[id] = new TriangleParser(x1,y1,z1,x2,y2,z2,x3,y3,z3,texture_id,material_id);
			else{
				printf("primitive id=%s triangle does not have all the correct attributes\n",id.c_str());
				getchar();
				exit(1);
			}
		}
		else if(type == "cylinder"){
			float base, top, height;
			int slices, stacks;
			if(prim->QueryFloatAttribute("base",&base)==TIXML_SUCCESS && 
				prim->QueryFloatAttribute("top",&top)==TIXML_SUCCESS &&
				prim->QueryFloatAttribute("height",&height)==TIXML_SUCCESS &&
				prim->QueryIntAttribute("slices",&slices)==TIXML_SUCCESS &&
				prim->QueryIntAttribute("stacks",&stacks)==TIXML_SUCCESS)
				primitives[id] = new CylinderParser(base,top,height,slices,stacks,texture_id,material_id);
			else{
				printf("cylinder does not have all the correct attributes\n");
				getchar();
				exit(1);
			}
		}
		else if(type == "sphere"){
			float radius;
			int slices, stacks;
			if(prim->QueryFloatAttribute("radius",&radius)==TIXML_SUCCESS && 
				prim->QueryIntAttribute("slices",&slices)==TIXML_SUCCESS &&
				prim->QueryIntAttribute("stacks",&stacks)==TIXML_SUCCESS)
				primitives[id] = new SphereParser(radius,slices,stacks,texture_id,material_id);
			else{
				printf("sphere does not have all the correct attributes\n");
				getchar();
				exit(1);
			}
		}
		else if(type == "torus"){
			float inner, outer;
			int slices, loops;
			if(prim->QueryFloatAttribute("inner",&inner)==TIXML_SUCCESS && 
				prim->QueryFloatAttribute("outer",&outer)==TIXML_SUCCESS &&
				prim->QueryIntAttribute("slices",&slices)==TIXML_SUCCESS &&
				prim->QueryIntAttribute("loops",&loops)==TIXML_SUCCESS)
				primitives[id] = new TorusParser(inner,outer,slices,loops,texture_id,material_id);
			else{
				printf("torus does not have all the correct attributes\n");
				getchar();
				exit(1);
			}
		}
		else{
			printf("primitive %s not valid\n",type.c_str());
			getchar();
			exit(1);
		}

	}while((primitiveElem = primitiveElem->NextSiblingElement()) != NULL);
}

void Parser::loadComponents(TiXmlElement* componentsElem){
	if(componentsElem == NULL){
		printf("components block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* componentElem = componentsElem->FirstChildElement("component");
	if(componentElem == NULL){
		printf("components block does not have children\n");
		getchar();
		exit(1);
	}

	string id;
	do{
		id = componentElem->Attribute("id");
		if(id.size() == 0){
			printf("component does not have id");
			getchar();
			exit(1);
		}
		string type;
		TiXmlElement* transformationElem = componentElem->FirstChildElement("transformation");
		if(transformationElem == NULL){
			printf("transformation block does not exist\n");
			getchar();
			exit(1);
		}

		ComponentParser component;
		TiXmlElement* transf = transformationElem->FirstChildElement();
		if(transf != NULL){
			string type;
			type = transf->Value();

			if(type == "transformationref"){
				component.transformation_id = transf->Attribute("id");
				if(id.size() == 0){
					printf("component does not have id");
					getchar();
					exit(1);
				}
			}
			else{
				float x,y,z,angle;
				char axis;
				vector<TransformationParser> transfors;
				do{
					type = transf->Value();
			
					if(type == "translate"){
						if (transf->QueryFloatAttribute("x",&x)==TIXML_SUCCESS && 
							transf->QueryFloatAttribute("y",&y)==TIXML_SUCCESS &&
							transf->QueryFloatAttribute("z",&z)==TIXML_SUCCESS)
							transfors.push_back( TransformationParser(TransformationParser::TRANSLATE,x,y,z));
						else
							printf("translate does not have all the correct attributes\n");
			
					}else if(type == "scale"){
						if (transf->QueryFloatAttribute("x",&x)==TIXML_SUCCESS && 
							transf->QueryFloatAttribute("y",&y)==TIXML_SUCCESS &&
							transf->QueryFloatAttribute("z",&z)==TIXML_SUCCESS)
							transfors.push_back( TransformationParser(TransformationParser::SCALE,x,y,z));
						else
							printf("scale does not have all the correct attributes\n");

					}else if(type == "rotate"){
						if (((axis = (transf->Attribute("axis"))[0])== 'x' || axis == 'y' || axis == 'z' ) && 
							transf->QueryFloatAttribute("angle",&angle)==TIXML_SUCCESS)
						{
							x = y = z = 0;
							switch(axis){
								case 'x':
									x = 1;
									break;
								case 'y':
									y = 1;
									break;
								case 'z':
									z = 1;
									break;
							}
							transfors.push_back( TransformationParser(TransformationParser::ROTATE,x,y,z,angle));
						}
						else
							printf("rotate does not have all the correct attributes\n");
					}else{
						printf("transformation not valid\n");
					}

				}while((transf = transf->NextSiblingElement()) != NULL);
				component.transformations = transfors;
			}
		}

		TiXmlElement* materialsElem = componentElem->FirstChildElement("materials");
		if(materialsElem == NULL){
			printf("materials block of component id = %s does not exist",id.c_str());
			getchar();
			exit(1);
		}
		string material_key;//= materialsElem->Attribute("key");
		if(materialsElem->Attribute("key")!=NULL){
			material_key = materialsElem->Attribute("key");
			if(material_key.size() > 1){
				printf("materials key of component id=%s is not a char",id.c_str());
				getchar();
				exit(1);
			}
			component.material_key = material_key[0];
		}
		TiXmlElement* matElem = materialsElem->FirstChildElement("material");
		if(matElem == NULL){
			printf("materials block of component id = %s does not have materials",id.c_str());
			getchar();
			exit(1);
		}
		string material_id;
		do{
			material_id = matElem->Attribute("id");
			if(material_id.size() == 0){
				printf("material of materials block of component id = %s does not have id",id.c_str());
				getchar();
				exit(1);
			}
			component.materials_id.push_back(material_id);
		}while((matElem = matElem->NextSiblingElement("material")) != NULL);

		TiXmlElement* textureElem = componentElem->FirstChildElement("texture");
		if(textureElem == NULL){
			printf("component id=%s does not have texture",id.c_str());
			getchar();
			exit(1);
		}
		if(textureElem->Attribute("id") == NULL){
			printf("texture of component id=%s does not have id", id.c_str());
			getchar();
			exit(1);
		}
		component.texture_id = textureElem->Attribute("id");

		TiXmlElement* childrenElem = componentElem->FirstChildElement("children");
		if(childrenElem == NULL){
			printf("children block does not exist\n");
			getchar();
			exit(1);
		}

		TiXmlElement* childElem = childrenElem->FirstChildElement();
		if(childElem == NULL){
			printf("children block does not have children\n");
			getchar();
			exit(1);
		}

		string child_id;
		do{
			type = childElem->Value();
			if(type == "componentref"){
				child_id = childElem->Attribute("id");
				if(child_id.size() == 0){
					printf("componentref does not have id");
					getchar();
					exit(1);
				}
				component.componentChildren_id.push_back(child_id);
			}
			else if(type == "primitiveref"){
				child_id = childElem->Attribute("id");
				if(child_id.size() == 0){
					printf("primitiveref does not have id");
					getchar();
					exit(1);
				}
				component.primitiveChildren_id.push_back(child_id);
			}
			else
				printf("child not valid\n");
		}while((childElem = childElem->NextSiblingElement()) != NULL);

		components[id] = component;
	}while((componentElem = componentElem->NextSiblingElement()) != NULL);
}

void Parser::loadFile(string filename){
	TiXmlDocument doc( filename.c_str() );
	bool loadOkay = doc.LoadFile();

	if ( !loadOkay )
	{
		printf( "Could not load test file %s. Error='%s'. Exiting.\n", filename.c_str(),doc.ErrorDesc() );
		getchar();
		exit( 1 );
	}
	TiXmlElement* dsx = doc.FirstChildElement("dsx");
	if(dsx == NULL){
		printf("dsx block does not exist\n");
		getchar();
		exit( 1 );
	}

	TiXmlElement* sceneElem = dsx->FirstChildElement("scene");
	if(dsx == NULL){
		printf("scene does not exist\n");
		getchar();
		exit( 1 );
	}
	root_id = sceneElem->Attribute("root");
	if(root_id.size()==0){
		printf("scene does not have a root\n");
		getchar();
		exit(1);
	}
	if(sceneElem->QueryFloatAttribute("axis_length",&axis_length)!= TIXML_SUCCESS){
		printf("axis_length not loaded correctly\n");
		exit(1);
	}

	TiXmlElement* viewsElem = dsx->FirstChildElement("views");
	TiXmlElement* illuminationElem = dsx->FirstChildElement("illumination");
	TiXmlElement* lightsElem = dsx->FirstChildElement("lights");
	TiXmlElement* transformationsElem = dsx->FirstChildElement("transformations");
	TiXmlElement* texturesElem = dsx->FirstChildElement("textures");
	TiXmlElement* materialsElem = dsx->FirstChildElement("materials");
	TiXmlElement* primitivesElem = dsx->FirstChildElement("primitives");
	TiXmlElement* componentsElem = dsx->FirstChildElement("components");

	loadViews(viewsElem);
	loadIllumination(illuminationElem);
	loadLights(lightsElem);
	loadTransformations(transformationsElem);
	loadTextures(texturesElem);
	loadMaterials(materialsElem);
	loadPrimitives(primitivesElem);
	loadComponents(componentsElem);
}

void Parser::showContents(){
	cout<< "SCENE " << "root = " << root_id << " axis_length = " << axis_length <<endl << endl;

	cout<< "ILLUMINATION: doublesided: "<<illumination.doublesided<<" local: "<<illumination.local<<endl;
	cout<< "\tambient:";
	for(int i = 0; i<4;++i)
		cout<<" "<<illumination.ambient[i];
	cout<<"\n\tbackground:";
	for(int i = 0; i<4;++i)
		cout<<" "<<illumination.background[i];

	map<string, vector<TransformationParser> >::iterator it = this->transformations.begin() ;
	cout << "\n\nTRANSFORMATIONS:" << endl;
	for(it; it != this->transformations.end(); ++it){
		cout << "Transformation id " << it->first << endl;
		for(int i = 0; i < it->second.size(); ++ i){
			string transformation_type;
			switch(it->second[i].transformation){
				case TransformationParser::TRANSLATE:
					transformation_type = "translate";
					break;
				case TransformationParser::SCALE:
					transformation_type = "scale";
					break;
				case TransformationParser::ROTATE:
					transformation_type = "rotate";
					break;
			}

			cout<< "\t"<< transformation_type << " x: " << it->second[i].x << " y: " << it->second[i].y << " z: " << it->second[i].z << " ang: " << it->second[i].ang << endl;
		}
	}

	map<string, PrimitiveParser* > primitives = this->primitives;
	map<string, PrimitiveParser* >::iterator it1 = primitives.begin();
	cout << endl << "PRIMITIVES:" <<endl;
	RectangleParser* rect; TriangleParser* tri; SphereParser* sph; CylinderParser* cyl; TorusParser* tor;
	for(it1; it1 != primitives.end(); ++it1){
		cout << "Primitive id " << it1->first << endl;
		cout<< "\tMaterial id = "<< it1->second->material_id <<endl;
		cout<< "\tTexture id = "<< it1->second->texture_id <<endl;
		switch(it1->second->getType()){
			case (PrimitiveParser::RECTANGLE):
				rect = ((RectangleParser*) it1->second);
				cout<< "\trectangle x1: "<< rect->x1 <<" y1: "<<rect->y1<<" x2: "<< rect->x2<< " y2: "<< rect->y2 <<endl;
				break;
			case (PrimitiveParser::TRIANGLE):
				tri = ((TriangleParser*) it1->second);
				cout<< "\ttriangle x1: "<< tri->x1 <<" y1: "<<tri->y1<<" z1: "<<tri->z1<<" x2: "<< tri->x2<< " y2: "<< tri->y2 
					<<" z2: "<<tri->z2<<" x3: "<< tri->x3<< " y3: "<< tri->y3 <<" z3: "<<tri->z3  <<endl;
				break;
			case (PrimitiveParser::SPHERE):
				sph = ((SphereParser*) it1->second);
				cout<< "\tsphere radius: "<< sph->radius <<" slices: "<<sph->slices<<" stacks: "<<sph->stacks<<endl;
				break;
			case (PrimitiveParser::CYLINDER):
				cyl = ((CylinderParser*) it1->second);
				cout<< "\tcylinder base: "<< cyl->base <<" top: "<<cyl->top<<" height: "<<cyl->height<<" slices: "<<cyl->slices<<" stacks: "<<cyl->stacks<<endl;
				break;
			case (PrimitiveParser::TORUS):
				tor = ((TorusParser*) it1->second);
				cout<< "\ttorus inner: "<< tor->inner <<" outer: "<<tor->outer<<" slices: "<<tor->slices<<" loops: "<<tor->loops<<endl;
				break;
		}
	}

	cout<<endl<<"TEXTURES:";
	for(map<string, TextureParser>::iterator tx_it=textures.begin(); tx_it != textures.end(); ++tx_it){
		cout<<endl<<endl<<"Texture id: "<< tx_it->first;
		cout<<endl<<"\tfile: "<< tx_it->second.file <<" length_s: " << tx_it->second.length_s <<" length_t: " << tx_it->second.length_t << " tx_id: "<< tx_it->second.tx_id;
	}

	getchar();

	cout<<endl<<"MATERIALS:";
	for(map<string, MaterialParser>::iterator mat_it=materials.begin(); mat_it != materials.end(); ++mat_it){
		cout<<endl<<endl<<"Material id: "<< mat_it->first;
		MaterialParser mat = mat_it->second;
		cout<<endl<<"\temission: ";
		for(int i=0;i<4;++i)
			cout<<mat.emission[i]<<" ";

		cout<<endl<<"\tambient: ";
		for(int i=0;i<4;++i)
			cout<<mat.ambient[i]<<" ";

		cout<<endl<<"\tdiffuse: ";
		for(int i=0;i<4;++i)
			cout<<mat.diffuse[i]<<" ";

		cout<<endl<<"\tspecular: ";
		for(int i=0;i<4;++i)
			cout<<mat.specular[i]<<" ";

		cout<<endl<<"\tshininess "<<mat.shininess[0]<<endl; 
	}

	cout<< endl << "COMPONENTS:";
	map<string, ComponentParser> components = this->components;
	map<string, ComponentParser>::iterator it2 = components.begin();
	for(it2; it2!= components.end();++it2){
		cout<<endl<<endl<<"Component id: "<< it2->first <<endl;
		ComponentParser comp = it2->second;

		cout<<"\tTransformation"<<endl;
		if(comp.transformations.size() == 0){
			if(comp.transformation_id.size() > 0){
				cout<<"\t\tTransformation id: "<<comp.transformation_id<<endl<<endl;
			}
			else{
				cout<<"\t\tDoes not have transformation"<<endl;
			}
		}
		else{
			for(int i = 0; i < comp.transformations.size(); ++ i){
				string transformation_type;
				switch(comp.transformations[i].transformation){
					case TransformationParser::TRANSLATE:
						transformation_type = "translate";
						break;
					case TransformationParser::SCALE:
						transformation_type = "scale";
						break;
					case TransformationParser::ROTATE:
						transformation_type = "rotate";
						break;
				}

				cout<< "\t\t"<< transformation_type << " x: " << comp.transformations[i].x << " y: " << comp.transformations[i].y << " z: " << comp.transformations[i].z << " ang: " << comp.transformations[i].ang << endl;
			}
		}

		cout << endl << "\tMaterials" << endl;
		if(comp.materials_id.size() == 1)
			cout << "\t\tmaterial id = " << comp.materials_id[0] <<endl;
		else{
			cout << "\t\tmaterials change with key %c" << comp.material_key <<endl;
			for(unsigned int i=0; i<comp.materials_id.size(); ++i){
				cout << "\t\tmaterial id = " << comp.materials_id[i] <<endl;
			}
		}

		cout << endl << "\tTextures" << endl;
		cout << "\t\ttexture id = " << comp.texture_id <<endl;

		cout << endl <<"\tChildren"<<endl<<"\t\tComponents: ";
		for(int i=0; i < comp.componentChildren_id.size();++i)
			cout<< " " << comp.componentChildren_id[i];
		cout<< endl<<"\t\tPrimitives: ";
		for(int i=0; i < comp.primitiveChildren_id.size();++i)
			cout<< " " << comp.primitiveChildren_id[i];
	}
}

void Parser::setComponentsTransformationMatrix(){
	vector<TransformationParser> trans;
	ComponentParser* component;

	for(map<string,ComponentParser>::iterator it = components.begin(); it != components.end();++it){
		component = &(it->second);
		glMatrixMode( GL_MODELVIEW );
		glLoadIdentity();

		if(component->transformations.size() == 0){
			if(component->transformation_id.size() > 0){
				trans = transformations[component->transformation_id];
			}
			else{
				trans.clear();
			}
		}
		else{
			trans = component->transformations;
		}

		for(unsigned int i = 0; i <  trans.size(); ++i){
			switch(trans[i].transformation){
				case TransformationParser::TRANSLATE:
					//printf("\nTRANSLATE\n");
					glTranslatef(trans[i].x,trans[i].y,trans[i].z);
					break;
				case TransformationParser::SCALE:
					//printf("\nSCALE\n");
					glScalef(trans[i].x,trans[i].y,trans[i].z);
					break;
				case TransformationParser::ROTATE:
					//printf("\nROTATE\n");
					glRotated(trans[i].ang,trans[i].x,trans[i].y,trans[i].z);
					break;
			}
		}
		/*float as[16];
		glGetFloatv(GL_MODELVIEW_MATRIX, as);
		for(int i = 0; i < 4;++i){
			for(int j=0; j <4; ++j){
				printf("%f ",as[i*4+j]);}
			printf("\n");
		}*/
		glGetFloatv(GL_MODELVIEW_MATRIX, component->transformation);

	}
}

void Parser::setComponentsChildren(){
	ComponentParser* component;
	map<string, ComponentParser>::iterator comp_it;
	map<string, PrimitiveParser* >::iterator prim_it;

	comp_it = components.find(root_id);
	if(comp_it == components.end()){
		printf("root id = %s does not exist\n",root_id.c_str());
		getchar();
		exit(1);
	}

	root = &(comp_it->second);

	for(map<string,ComponentParser>::iterator it = components.begin(); it != components.end();++it){
		component = &(it->second);

		for(unsigned int i=0;i<component->componentChildren_id.size();++i){
			comp_it = components.find(component->componentChildren_id[i]);
			if(comp_it == components.end()){
				printf("component id = %s does not exist\n", component->componentChildren_id[i].c_str());
				getchar();
				exit(1);
			}
			component->componentChildren.push_back(&(comp_it->second));
		}

		for(unsigned int i=0;i<component->primitiveChildren_id.size();++i){
			prim_it = primitives.find(component->primitiveChildren_id[i]);
			if(prim_it == primitives.end()){
				printf("primitive id = %s does not exist\n", component->primitiveChildren_id[i].c_str());
				getchar();
				exit(1);
			}
			component->primitiveChildren.push_back(prim_it->second);
		}
	}
}

void Parser::setMaterials(){
	for(map<string, PrimitiveParser* >::iterator it = primitives.begin(); it != primitives.end(); ++it){
		PrimitiveParser* prim = it->second;

		if(prim->material_id != "inherit"){
			map<string, MaterialParser>::iterator mat_it = materials.find(prim->material_id);
			if(mat_it == materials.end()){
				printf("material id = %s of primitive id = %s does not exist",prim->material_id.c_str(),it->first.c_str());
				getchar();
				exit(1);
			}

			prim->material = &(mat_it->second);
		}
	}

	for(map<string, ComponentParser>::iterator it = components.begin(); it != components.end(); ++it){
		ComponentParser* comp = &(it->second);
		MaterialParser* inherit_mat = NULL;
		if(comp->materials_id.size() > 1){
			if(changing_materials.find(comp->material_key) != changing_materials.end()){
				printf("key %c is already used by another component", comp->material_key);
				getchar();
				exit(1);
			}
			changing_materials[comp->material_key] = comp;
		}

		for(int i=0; i<comp->materials_id.size(); ++i){
			if(comp->materials_id[i] != "inherit"){
				map<string, MaterialParser>::iterator mat_it = materials.find(comp->materials_id[i]);
				if(mat_it == materials.end()){
					printf("material id = %s of component id = %s does not exist",comp->materials_id[i].c_str(),it->first.c_str());
					getchar();
					exit(1);
				}

				comp->materials.push_back( &(mat_it->second) );
			}
			else
				comp->materials.push_back(inherit_mat);
		}
	}
}

void Parser::setTextures(){
	for(map<string,TextureParser>::iterator tx_it= textures.begin(); tx_it != textures.end(); ++tx_it){
		map<string, int>::iterator txId_it;
		if((txId_it = textures_id.find(tx_it->second.file)) != textures_id.end())
			tx_it->second.tx_id = txId_it->second;
		else{
			if(pixmap.readBMPFile(tx_it->second.file.c_str()) == 0){
				printf("file %s does not exist", tx_it->second.file.c_str());
				getchar();
				exit(1);
			}
			pixmap.setTexture(++n_textures);
			textures_id[tx_it->second.file] = n_textures;
			tx_it->second.tx_id = n_textures;
		}
	}

	for(map<string, PrimitiveParser* >::iterator it = primitives.begin(); it != primitives.end(); ++it){
		PrimitiveParser* prim = it->second;

		if(prim->texture_id != "inherit" && prim->texture_id != "none"){
			map<string, TextureParser>::iterator tx_it = textures.find(prim->texture_id);
			if(tx_it == textures.end()){
				printf("texture id = %s of primitive id = %s does not exist",prim->texture_id.c_str(),it->first.c_str());
				getchar();
				exit(1);
			}

			prim->texture = &(tx_it->second);
		}
	}

	for(map<string, ComponentParser >::iterator it = components.begin(); it != components.end(); ++it){
		ComponentParser* comp = &(it->second);

		if(comp->texture_id != "inherit" && comp->texture_id != "none"){
			map<string, TextureParser>::iterator tx_it = textures.find(comp->texture_id);
			if(tx_it == textures.end()){
				printf("texture id = %s of component id = %s does not exist",comp->texture_id.c_str(),it->first.c_str());
				getchar();
				exit(1);
			}

			comp->texture = &(tx_it->second);
		}
	}
}

void Parser::drawScene(){
	//glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	//glLoadIdentity();
	processComponent(root);
	glPopMatrix();
}

void Parser::processComponent(ComponentParser* comp){
	glPushMatrix();
	glMultMatrixf(comp->transformation);
	
	int material_index = comp->material_index;
	bool material_not_inherit = false;
	if(comp->materials_id[material_index] != "inherit"){
		materials_stack.push(comp->materials[material_index]);
		material_not_inherit = true;
	}

	//TextureParser* tx_null = NULL;
	bool texture_not_inherit = false;
	if(comp->texture_id != "inherit"){
		if(comp->texture_id != "none")
			textures_stack.push(comp->texture);
		else
			textures_stack.push(NULL/*tx_null*/);
		texture_not_inherit = true;
	}

	for(unsigned int i=0; i<comp->componentChildren.size();++i){
		processComponent(comp->componentChildren[i]);
	}

	for(unsigned int i=0; i<comp->primitiveChildren.size();++i){
		processPrimitive(comp->primitiveChildren[i]);
	}
	if(material_not_inherit)
		materials_stack.pop();
	if(texture_not_inherit)
		textures_stack.pop();
	glPopMatrix();
}

void Parser::processPrimitive(PrimitiveParser* prim){
	if(prim->material_id != "inherit")
		prim->material->applyMaterial();
	else if(!materials_stack.empty())
		materials_stack.top()->applyMaterial();

	if(prim->texture_id != "inherit")
		prim->render();
	else{
		if(textures_stack.top() == NULL)
			prim->render();
		else
			prim->render(textures_stack.top());
	}
}